//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.goldhuman.IO.Protocol;

import com.goldhuman.Common.Marshal.OctetsStream;
import com.goldhuman.Common.Octets;
import com.goldhuman.Common.TimerObserver;
import com.goldhuman.IO.NetIO.NetSession;

import java.net.SocketAddress;
import java.util.LinkedList;

public final class Session extends NetSession {
    protected Manager manager;
    protected static boolean need_wakeup = false;
    private State state;
    private com.goldhuman.IO.Protocol.Stream is;
    private LinkedList<OctetsStream> os;
    private TimerObserver.WatchDog timer;
    private long timestamp;
    private LinkedList<java.lang.Runnable> private_tasks;

    public void AddTask(java.lang.Runnable r) {
        synchronized(this.private_tasks) {
            if (this.private_tasks.isEmpty()) {
                this.private_tasks.addFirst(r);
                (new Thread(new java.lang.Runnable() {
                    public void run() {
                        while(true) {
                            java.lang.Runnable r = null;
                            synchronized(Session.this.private_tasks) {
                                r = (Runnable)Session.this.private_tasks.getLast();
                            }

                            r.run();
                            synchronized(Session.this.private_tasks) {
                                Session.this.private_tasks.removeLast();
                                if (Session.this.private_tasks.isEmpty()) {
                                    return;
                                }
                            }
                        }
                    }
                })).start();
            } else {
                this.private_tasks.addFirst(r);
            }

            this.private_tasks.notify();
        }
    }

    public Object clone() {
        try {
            Session s = (Session)super.clone();
            s.state = new State(this.state);
            s.is = new Stream(s);
            s.os = new LinkedList();
            s.private_tasks = new LinkedList();
            s.timer = new TimerObserver.WatchDog();
            return s;
        } catch (Exception var2) {
            return null;
        }
    }

    public String Identification() {
        return this.manager.Identification();
    }

    public SocketAddress OnCheckAddress(SocketAddress sa) {
        return this.manager.OnCheckAddress(sa);
    }

    protected void OnOpen() {
        this.timer.Reset();
        this.manager.AddSession(this);
    }

    protected void OnClose() {
        this.manager.DelSession(this);
    }

    public void OnAbort() {
        this.manager.AbortSession(this);
    }

    public long getTimestamp() {
        return this.timestamp;
    }

    protected void OnRecv() {
        this.timestamp = System.currentTimeMillis();
        this.timer.Reset();
        Octets input = this.Input();
        this.is.insert(this.is.size(), input);
        input.clear();

        Protocol p;
        try {
            while((p = Protocol.Decode(this.is)) != null) {
                Task.Dispatch(this.manager, this, p);
            }
        } catch (ProtocolException var3) {
            this.Close();
        }

    }

    protected void OnSend() {
        if (this.state.TimePolicy(this.timer.Elapse())) {
            if (this.os.size() != 0) {
                do {
                    OctetsStream o = (OctetsStream)this.os.getFirst();
                    if (!this.Output(o)) {
                        break;
                    }

                    this.os.removeFirst();
                } while(this.os.size() != 0);

                this.timer.Reset();
            }
        } else {
            this.Close();
        }

    }

    protected boolean Send(Protocol protocol) {
        synchronized(this) {
            OctetsStream o = new OctetsStream();
            protocol.Encode(o);
            if (protocol.SizePolicy(o.size())) {
                this.os.addLast(o);
                need_wakeup = true;
                return true;
            } else {
                return false;
            }
        }
    }

    protected boolean StatePolicy(int type) {
        return this.state.TypePolicy(type);
    }

    protected void Close() {
        this.closing = true;
    }

    protected void ChangeState(String name) {
        synchronized(this) {
            this.state = State.Get(name);
        }
    }

    public Session(Manager m) {
        this.manager = m;
        this.state = this.manager.GetInitState();
    }
}
